package waggle.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

import waggle.client.i18n.AppConstants;

/**
 * A simple table widget that supported RPC call.
 * 
 * Note: to make the table resizes correctly on resize onChange go to .CSS file
 * and make the headers width percentages added up to be 100%
 * 
 * @author Tri
 * 
 */
public class TableWidget extends Composite {

	private static final AppConstants constants = ApplicationView
			.getConstants();

	private final int columnCount;
	private final SimplePanel headerContainer = new SimplePanel();
	private final SimplePanel footerPanel = new SimplePanel();
	private final VerticalPanel table = new VerticalPanel();
	private final HorizontalPanel header = new HorizontalPanel();
	private final VerticalPanel outer = new VerticalPanel();

	/**
	 * Initializes this TableWidget.
	 * 
	 * @param dataProvider
	 *            a TableDataProvider for this table.
	 * @param columns
	 *            column header names for this table.
	 * @param columnStyles
	 *            column header CSS style names associates with column header
	 *            names.
	 * @param rowCount
	 *            total row of this table
	 */
	public TableWidget(String columns[], String columnStyles[], int rowCount) {
		if (columns.length == 0) {
			throw new IllegalArgumentException(
					"expecting a positive number of columns");
		}

		if (columnStyles != null && columns.length != columnStyles.length) {
			throw new IllegalArgumentException(
					"expecting as many styles as columns");
		}

		columnCount = columns.length;
		headerContainer.setWidget(header);
		headerContainer.setStyleName("header");

		initWidget(outer);
		table.setStyleName("table");
		initTableOutLine();
		initHeader(columns, columnStyles, rowCount);
		setStyleName("Table-TableWidget");
		outer.setSpacing(0);

		footerPanel.setStyleName("footer");
		// table.addTableListener(headerListener);
	}

	/**
	 * Initializes this TableWidget.
	 * 
	 * @param dataProvider
	 *            a TableDataProvider for this table.
	 * @param columns
	 *            column header names for this table.
	 * @param columnStyles
	 *            column header CSS style names associates with column header
	 *            names.
	 * @param rowCount
	 *            total row of this table
	 */
	public TableWidget(Widget columns[], String columnStyles[], int rowCount) {
		if (columns.length == 0) {
			throw new IllegalArgumentException(
					"expecting a positive number of columns");
		}

		if (columnStyles != null && columns.length != columnStyles.length) {
			throw new IllegalArgumentException(
					"expecting as many styles as columns");
		}
		columnCount = columns.length;
		headerContainer.setWidget(header);
		headerContainer.setStyleName("header");

		initWidget(outer);
		table.setStyleName("table");
		initTableOutLine();
		initHeader(columns, columnStyles, rowCount);
		setStyleName("Table-TableWidget");
		outer.setSpacing(0);

		footerPanel.setStyleName("footer");
		// table.addTableListener(headerListener);
		// grid.setCellPadding(0);
		// grid.setCellSpacing(0);
	}

	public void showRecord(int pageSize, int startRow, Widget data[][]) {
		int totalRow = data.length;
		int destColCount = header.getWidgetCount();
		resize(totalRow, pageSize, startRow);
		for (int row = startRow, rowData = 0; row < startRow
				+ (table.getWidgetCount() - (startRow % pageSize)); row++, rowData++) {
			Widget[] srcRowData = data[rowData];
			HorizontalPanel rowPanel = getRow(rowData);
			rowPanel.clear();
			assert (srcRowData.length == destColCount) : " "
					+ constants.ColMismatch();
			for (int srcColIndex = 0; srcColIndex < destColCount; ++srcColIndex) {
				Widget cellWidget = srcRowData[srcColIndex];
				cellWidget.setStyleName("col-"
						+ header.getWidget(srcColIndex).getStyleName());
				rowPanel.add(cellWidget);
				// grid.setWidget(destRowIndex, srcColIndex, cellWidget);
				// grid.getCellFormatter().setStyleName(destRowIndex,
				// srcColIndex,
				// " row");
			}
		}
	}

	/**
	 * Gets data table row count.
	 * 
	 * @return the data table row count.
	 */
	public int getDataRowCount() {
		return table.getWidgetCount();
	}

	/**
	 * Gets the cell widget of the given row and column.
	 * 
	 * @param row
	 *            of this table
	 * @param col
	 *            of this table
	 * @return the cell widget of the given row and column.
	 */
	public Widget getCellWidget(int row, int col) {
		return getRow(row).getWidget(col);
	}
	
	  public void resetHeader(String columns[], String columnStyles[]) {
		    header.clear();
		    initHeader(columns, columnStyles, 0);
		  }
	
	  private final Map<String, Integer> headerColMap = new HashMap<String, Integer>();
	  
	  /**
	   * A helper to initialize table widget with columns names are normal strings.
	   * 
	   * @param columns column header names for this table.
	   * @param columnStyles column header CSS style names associates with column
	   * header names.
	   * @param rowCount total row of this table
	   */
	  private void initHeader(String[] columns, String[] columnStyles, int rowCount) {
	    // Set up the header row. It's one greater than the number of visible
	    // rows.
	    //
	    // grid.resize(rowCount + 1, columns.length);
	    // header.setStyleName("header");
	    for (int i = 0, n = columns.length; i < n; i++) {
	      // grid.setText(0, i, columns[i]);
	      Label headerLb = new Label(columns[i]);
	      header.add(headerLb);
	      headerColMap.put(columns[i], i);
	      if (columnStyles != null) {
	        headerLb.setStyleName(columnStyles[i]);
	      }
	    }
	    table.clear();
	  }

	  /**
	   * Sets table view after the navigation bar.
	   */
	  private void initTableOutLine() {
	    outer.clear();
	    // outer.add(navbar);
	    outer.add(headerContainer);
	    outer.add(table);
	    outer.add(footerPanel);
	  }
	  /**
	   * A helper to initialize table widget with columns names are widgets.
	   * 
	   * @param columns column header names for this table.
	   * @param columnStyles column header CSS style names associates with column
	   * header names.
	   * @param rowCount total row of this table
	   */
	  private void initHeader(Widget[] columns, String[] columnStyles, int rowCount) {
	    // Set up the header row. It's one greater than the number of visible
	    // rows.
	    //
	    // header.setStyleName("header");
	    for (int i = 0, n = columns.length; i < n; i++) {
	      header.add(columns[i]);
	      if (columnStyles != null) {
	        header.setStyleName(columnStyles[i]);
	      }
	    }
	    table.clear();
	  }

	  /**
	   * Resizes the data table with the given row count.
	   * 
	   * @param rowCount number of row of the current view.
	   */
	  private void resize(int rowCount, int pageSize, int startRow) {
	    if (rowCount == 0) {
	      table.clear();
	      return;
	    }
	    if (rowCount >= pageSize || startRow % pageSize == 0) {
	      table.clear();
	    }
	    for (int row = 0; row < rowCount % (pageSize + 1); row++) {
	      SimplePanel panel = new SimplePanel();
	      HorizontalPanel rowPanel = new HorizontalPanel();
	      panel.setWidget(rowPanel);
	      panel.setStyleName("row");
	      table.add(panel);
	    }
	    if (rowCount < pageSize) {
	      // grid.resizeRows(rowCount + 1);
	    } else {
	      // grid.resizeRows(pageSize + 1);
	    }
	  }

	  private HorizontalPanel getRow(int row) {
		    return (HorizontalPanel) ((SimplePanel) table.getWidget(row)).getWidget();
		  }
	  
}
